//! # 错误处理和异常场景测试
//!
//! 提供消息总线系统各种错误和异常情况的全面测试覆盖

#[cfg(test)]
mod error_handling_tests {
    use crate::prelude::*;
    use crate::mock::{MockMessageBus, MockSubscriber, MockBehavior, test_helpers::*};
    use crate::publisher::SimplePublisher;
    use serde_json::json;
    use std::sync::Arc;
    use tokio::time::{timeout, Duration};

    /// 消息总线错误测试
    mod message_bus_error_tests {
        use super::*;

        #[tokio::test]
        async fn test_publish_connection_error() {
            let bus = MockMessageBus::new();
            bus.set_behavior("publish", MockBehavior::new().with_failure("连接错误")).await;
            
            let message = create_test_message("error.topic", json!({"test": "connection"}));
            let result = bus.publish(message).await;
            
            assert!(result.is_err());
            assert!(result.unwrap_err().to_string().contains("连接错误"));
        }

        #[tokio::test]
        async fn test_publish_timeout_error() {
            let bus = MockMessageBus::new();
            bus.set_behavior("publish", MockBehavior::new().with_timeout()).await;
            
            let message = create_test_message("timeout.topic", json!({"test": "timeout"}));
            let result = timeout(Duration::from_millis(100), bus.publish(message)).await;
            assert!(result.is_err());
        }

        #[tokio::test]
        async fn test_operations_after_close() {
            let bus = MockMessageBus::new();
            bus.close().await.unwrap();
            
            let message = create_test_message("after.close", json!({"test": "closed"}));
            let publish_result = bus.publish(message).await;
            assert!(publish_result.is_err());
            
            let subscribe_result = bus.subscribe("after.close").await;
            assert!(subscribe_result.is_err());
        }

        #[tokio::test]
        async fn test_invalid_topic_names() {
            let bus = MockMessageBus::new();
            let invalid_topics = vec!["", "   ", "topic..sub", ".topic", "topic."];
            
            for topic in invalid_topics {
                let message = Message::new(topic, json!({"test": "invalid"}));
                bus.set_behavior("publish", MockBehavior::new().with_failure("无效主题")).await;
                let result = bus.publish(message).await;
                assert!(result.is_err(), "主题 '{}' 应该失败", topic);
                bus.set_behavior("publish", MockBehavior::new()).await;
            }
        }
    }

    /// 订阅者错误测试
    mod subscriber_error_tests {
        use super::*;

        #[tokio::test]
        async fn test_receive_after_close() {
            let mut subscriber = MockSubscriber::new("test.topic");
            let message = create_test_message("test.topic", json!({"before": "close"}));
            subscriber.add_message(message).await;
            subscriber.close().await.unwrap();
            
            assert!(subscriber.receive().await.is_err());
            assert!(subscriber.try_receive().await.is_err());
            assert!(subscriber.receive_timeout(100).await.is_err());
        }

        #[tokio::test]
        async fn test_ack_nack_after_close() {
            let subscriber = MockSubscriber::new("test.topic");
            let message = create_test_message("test.topic", json!({"test": "ack_nack"}));
            subscriber.close().await.unwrap();
            
            assert!(subscriber.ack(&message).await.is_err());
            assert!(subscriber.nack(&message, false).await.is_err());
        }
    }

    /// 并发错误场景测试
    mod concurrent_error_tests {
        use super::*;
        use std::sync::atomic::{AtomicUsize, Ordering};

        #[tokio::test]
        async fn test_concurrent_errors() {
            let bus = Arc::new(MockMessageBus::new());
            bus.set_behavior("publish", MockBehavior::new().with_call_limit(5)).await;
            
            let success_count = Arc::new(AtomicUsize::new(0));
            let error_count = Arc::new(AtomicUsize::new(0));
            let mut handles = vec![];
            
            for i in 0..10 {
                let bus_clone = bus.clone();
                let success_counter = success_count.clone();
                let error_counter = error_count.clone();
                
                let handle = tokio::spawn(async move {
                    let message = create_test_message("concurrent.error", json!({"id": i}));
                    match bus_clone.publish(message).await {
                        Ok(_) => { success_counter.fetch_add(1, Ordering::Relaxed); }
                        Err(_) => { error_counter.fetch_add(1, Ordering::Relaxed); }
                    }
                });
                handles.push(handle);
            }
            
            for handle in handles {
                handle.await.unwrap();
            }
            
            assert_eq!(success_count.load(Ordering::Relaxed), 5);
            assert_eq!(error_count.load(Ordering::Relaxed), 5);
        }

        #[tokio::test]
        async fn test_error_recovery() {
            let bus = Arc::new(MockMessageBus::new());
            
            // 第一阶段：设置失败
            bus.set_behavior("publish", MockBehavior::new().with_failure("临时错误")).await;
            let message1 = create_test_message("recovery.test", json!({"phase": 1}));
            assert!(bus.publish(message1).await.is_err());
            
            // 第二阶段：恢复正常
            bus.set_behavior("publish", MockBehavior::new()).await;
            let message2 = create_test_message("recovery.test", json!({"phase": 2}));
            assert!(bus.publish(message2).await.is_ok());
            
            let published = bus.get_published_messages().await;
            assert_eq!(published.len(), 1);
            assert_eq!(published[0].payload()["phase"], 2);
        }
    }

    /// 资源清理测试
    mod resource_cleanup_tests {
        use super::*;

        #[tokio::test]
        async fn test_cleanup_after_errors() {
            let bus = Arc::new(MockMessageBus::new());
            let subscriber = bus.subscribe("cleanup.test").await.unwrap();
            
            bus.set_behavior("publish", MockBehavior::new().with_failure("操作失败")).await;
            let message = create_test_message("cleanup.test", json!({"test": "cleanup"}));
            assert!(bus.publish(message).await.is_err());
            
            let count_before = bus.subscriber_count("cleanup.test").await.unwrap();
            assert_eq!(count_before, 1);
            
            bus.unsubscribe(subscriber.subscription_id()).await.unwrap();
            let count_after = bus.subscriber_count("cleanup.test").await.unwrap();
            assert_eq!(count_after, 0);
        }
    }
}